﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace Space_Conquest
{
    public partial class GameForm : Form, IDisposable
    {

        #region Variables

        /// <summary>
        /// Tracks wether DX Device is Lost or not (caused by minimizing)
        /// </summary>
        private bool bDeviceActive = false;

        /// <summary>
        /// DirectX Device Settings, used to Initialize and Reset the DX Device
        /// </summary>
        private PresentParameters ppPresent = new PresentParameters();

        #endregion

        #region Construtor

        /// <summary>
        /// Creates form, Initializes the Form and DirectX
        /// </summary>
        public GameForm()
        {

            // Form Designer Initializations
            InitializeComponent();

            // Set Styles and others
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);

            this.Height = 500;
            this.Width = 500;

            // Initialize DirectX
            InitializeDevice();
        }

        #endregion

        #region Motion

        /// <summary>
        /// Game Logic / Unit Movement Happens here
        /// </summary>
        public void Motion()
        {
            GameEvents.Motion();
        }

        #endregion

        #region Render

        /// <summary>
        /// Sprite / Texture / Text Render happens here
        /// </summary>
        public void Render()
        {

            try
            {

                int result;

                if (Globals.device.CheckCooperativeLevel(out result) && bDeviceActive)
                {

                    Globals.device.Clear(ClearFlags.Target, Color.Black, (float)1.0, 0);
                    Globals.device.BeginScene();

                    GameEvents.Render();

                    Globals.device.EndScene();
                    Globals.device.Present();

                    this.Invalidate();

                }
                else if (result == (int)ResultCode.DeviceLost)
                {
                    Thread.Sleep(500);    //Can't Reset yet, wait for a bit
                }
                else if (result == (int)ResultCode.DeviceNotReset)
                {
                    ResetDevice();
                }

            }
            catch (Exception ex)
            {
                if (bDeviceActive)
                {
                    Console.WriteLine("Unexpected Error: " + ex.Message);
                    Globals.bRunning = false;
                }

            }

        }

        #endregion

        #region Input Events

        /// <summary>
        /// Mouse Button is Pressed Down
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_MouseDown(object sender, MouseEventArgs e)
        {
            GameEvents.MouseDown(e.Button, e.X, e.Y);
        }

        /// <summary>
        /// Mouse button is let up
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_MouseUp(object sender, MouseEventArgs e)
        {
            GameEvents.MouseUp(e.Button, e.X, e.Y);
        }

        /// <summary>
        /// Mouse cursor is moved around Screen
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_MouseMove(object sender, MouseEventArgs e)
        {
            GameEvents.MouseMove(e.X, e.Y);
        }

        /// <summary>
        /// A key on keyboard is pressed down
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_KeyDown(object sender, KeyEventArgs e)
        {
            GameEvents.KeyDown(e.KeyCode, e.Shift);
        }

        /// <summary>
        /// A key on keyboard is let up after being pressed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_KeyUp(object sender, KeyEventArgs e)
        {
            GameEvents.KeyUp(e.KeyCode, e.Shift);
        }

        #endregion

        #region Initialize / Reset DirectX
        /// <summary>
        /// Set up DirectX with the GameForm
        /// </summary>
        private void InitializeDevice()
        {

            ppPresent.Windowed = false;
            ppPresent.BackBufferCount = 1;
            ppPresent.EnableAutoDepthStencil = false;
            ppPresent.DeviceWindow = this;
            ppPresent.PresentationInterval = PresentInterval.Immediate;
            ppPresent.SwapEffect = SwapEffect.Discard;

            // check monitor; different resolution for widescreen
            if (((double)Screen.PrimaryScreen.Bounds.Width / (double)Screen.PrimaryScreen.Bounds.Height) > 1.4)
            {

                ppPresent.BackBufferWidth = 1280;
                ppPresent.BackBufferHeight = 720;

                Globals.iScreenWidth = 1280;
                Globals.iScreenHeight = 720;


            }
            else
            {

                ppPresent.BackBufferWidth = 1024;
                ppPresent.BackBufferHeight = 768;

                Globals.iScreenWidth = 1024;
                Globals.iScreenHeight = 768;


            }

            ppPresent.BackBufferFormat = Format.R5G6B5;

            Globals.device = new Microsoft.DirectX.Direct3D.Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, ppPresent);

            Globals.device.VertexFormat = CustomVertex.TransformedColoredTextured.Format;
            Globals.device.SetRenderState(RenderStates.Lighting, false);
            Globals.device.SetRenderState(RenderStates.SourceBlend, (int)Blend.SourceAlpha);
            Globals.device.SetRenderState(RenderStates.DestinationBlend, (int)Blend.InvSourceAlpha);
            Globals.device.SetRenderState(RenderStates.AlphaBlendEnable, true);
            Globals.device.SetTextureStageState(0, TextureStageStates.AlphaOperation, (int)TextureOperation.Modulate);
            Globals.device.DeviceResizing += new System.ComponentModel.CancelEventHandler(this.CancelResize);

            bDeviceActive = true;

        }

        private void ResetDevice()
        {

            Globals.device.Reset(ppPresent);

            Globals.device.VertexFormat = CustomVertex.TransformedColoredTextured.Format;
            Globals.device.SetRenderState(RenderStates.Lighting, false);
            Globals.device.SetRenderState(RenderStates.SourceBlend, (int)Blend.SourceAlpha);
            Globals.device.SetRenderState(RenderStates.DestinationBlend, (int)Blend.InvSourceAlpha);
            Globals.device.SetRenderState(RenderStates.AlphaBlendEnable, true);
            Globals.device.SetTextureStageState(0, TextureStageStates.AlphaOperation, (int)TextureOperation.Modulate);

            bDeviceActive = true;

        }


        #endregion

        #region IDisposable Members

        /// <summary>
        /// Dispose of resources being used
        /// </summary>
        void IDisposable.Dispose()
        {

            // Dispose DirectX Objects
            DisposeDXDevice();

            // Dispose Windows Form
            base.Dispose();

        }

        /// <summary>
        /// Dispose of DirectX Device that GameForm is using
        /// </summary>
        private void DisposeDXDevice()
        {
            Globals.device.Dispose();
            Globals.device = null;
        }

        #endregion

        #region Other Events

        /// <summary>
        /// Form loses focus because of minimize or Alt+Tab / Deactivates DX device
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_Deactivate(object sender, EventArgs e)
        {
            bDeviceActive = false;
        }

        /// <summary>
        /// Cancels screen resizing (resizing can cause DX Device to be lost)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CancelResize(object sender, System.ComponentModel.CancelEventArgs e)
        {
            e.Cancel = true;
        }

        /// <summary>
        /// Call EndProgram() if user closes from Task Bar after minimizing
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_FormClosed(object sender, FormClosedEventArgs e)
        {
            Globals.EndProgram();
        }

        /// <summary>
        /// Form loads when created
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmMain_Load(object sender, EventArgs e)
        {

        }

        #endregion


    }

}
